/*
 *Copyright (c) 2008, Scendix Software, Inc.
 * 
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Data;
using System.Diagnostics;
using Microsoft.MediaCenter.UI;
using System.Reflection;
using Redemption;


namespace mceTapiRexv2
{
    /// <summary>
    /// This object contains the standard set of information displayed in the 
    /// details page UI.
    /// </summary>
    public class Contacts : ModelItem
    {
        private static List<Contact> lstContacts = new List<Contact>();
        private int currPage = 0;
        private int maxPage;
        private bool bGroupView;
        private List<Group> lstGroup = new List<Group>(); 
        private Int16 intItemsPerPage = 20;
        private String strGroupBy;
        private String strCurrentGroup;
        private mceTapiRexv2.Utils.connectDB db = new mceTapiRexv2.Utils.connectDB();
        private String sFilter = "";
        private int offset;

        public List<Contact> ContactList
        {
            get
            {
               // if(GroupBy!=null&&CurrentGroup!=null)
                return lstContacts;
            }
        }
        public List<Group> GroupList
        {
            get
            {
                 return lstGroup;
            }
        }
        public Int16 ItemsPP
        {
            get
            {
                return intItemsPerPage;
            }
            set
            {
                intItemsPerPage = value;
            }
        }
        public String GroupBy
        {
            get
            {
                return strGroupBy;
            }
            set
            {
                if (value == "Company" && !mceTapiRexv2.Application.Current.isDatabasePrimarySource())
                    strGroupBy = "CompanyName";
                else
                  strGroupBy = value;
                loadGroups();
            }
        }
        public String CurrentGroup
        {
            get { return strCurrentGroup; }
            set { strCurrentGroup = value; }
        }
        private void loadGroups()
        {
            if (mceTapiRexv2.Application.Current.isDatabasePrimarySource())
                loadGroupsFromDatabase();
            else loadGroupsFromOutlook();
        }
        private String buildGroupCondition()
        {
            List<String> cond = new List<string>();
            string condition = "";
            if (this.sFilter != null && this.sFilter != "")
            {
                List<string> criterias = new List<string>();
                criterias.Add(GroupBy);
                string keywordCond = "";
                string neg = "";
                string[] words = this.sFilter.Split(' ');
                int i = 0;
                foreach (string word in words)
                {
                    string searchExpression = word.Trim();
                    if (searchExpression == "" || searchExpression == " " || searchExpression == "-") break;
                    string condOp;
                    if (searchExpression.Substring(0, 1) == "-")
                    {
                        neg = "NOT";
                        condOp = " AND ";
                        searchExpression = searchExpression.Substring(1);
                    }
                    else condOp = " OR ";
                    if (i++ > 0) keywordCond += " AND ";
                    int j = 0;
                    foreach (string crit in criterias)
                    {
                        if (j++ == 0) keywordCond += "(";
                        else keywordCond += condOp;
                        keywordCond += "((" + crit + ") " + neg + " LIKE '%" + searchExpression + "%')";
                    }
                    keywordCond += ")";
                    cond.Add(keywordCond);
                }
            }
             string tempCondition = "";
            if (cond.Count > 0)
            {
                int j = 0;

                foreach (String sCondition in cond)
                {
                    if (j++ > 0) tempCondition += " AND ";
                    tempCondition += sCondition;
                }
            }
            if (tempCondition != "")
                tempCondition = "WHERE " + tempCondition;
            return tempCondition;
           

        }
        private void loadGroupsFromDatabase()
        {
            if (GroupBy != null)
            {
                
                string strSQL = "SELECT Count(*)," + GroupBy + 
                    " FROM  Contacts "+ buildGroupCondition() + " GROUP BY " + GroupBy ;
                lstGroup = new List<Group>();
                DataSet dr = db.SelectQuery(strSQL);
                DataTable dt = dr.Tables[0];
                if (dt != null && dt.Rows.Count > 0)
                {
                    foreach (DataRow row in dt.Rows)
                    {
                        if (row[1].ToString() != "")
                        {
                            Group gui = new Group();
                            gui.Count = row[0].ToString();
                            gui.Name = row[1].ToString();
                            lstGroup.Add(gui);
                        }
                        else
                        {
                            if (row[0].ToString() != "0")
                            {
                                Group other = new Group();
                                other.Count = row[0].ToString();
                                other.Name = mceTapiRexv2.Application.Current.getResString("1504", "", "");
                                lstGroup.Add(other);
                            }
                        }

                    }
                }
            }
            FirePropertyChanged("GroupList");
        }
        private List<string> getProperties()
        {
            if (mceTapiRexv2.Application.Current.isDatabasePrimarySource())
            {
                List<string> criterias = new List<string>();
                criterias.Add("LastName");
                criterias.Add("FirstName");
                criterias.Add("Company");
                criterias.Add("TelPrivate");
                criterias.Add("TelCompany");
                criterias.Add("Mobile");
                criterias.Add("Fax");
                return criterias;
            }
            else
            {
                List<string> criterias = new List<string>();
                criterias.Add("FullName");
                criterias.Add("Email1Address");
                criterias.Add("Email2Address");
                criterias.Add("Email2Address");
                criterias.Add("HomeAddress");
                criterias.Add("HomeAddressCity");
                criterias.Add("BusinessAddressCity");
                criterias.Add("OtherAddressCity");
                criterias.Add("HomeTelephoneNumber");
                criterias.Add("BusinessTelephoneNumber");
                criterias.Add("OtherTelephoneNumber");
                return criterias;
            }  
            
        }
        private void loadGroupsFromOutlook()
        {
            if (GroupBy != null)
            {
                string groupCond = buildGroupCondition();
                groupCond = groupCond.Replace("WHERE", " AND ");
                string strSQL = "SELECT * FROM  Folder WHERE MessageClass='IPM.Contact' " +
                groupCond + "ORDER BY " + GroupBy ;
                lstGroup = new List<Group>();
                RDOSession session = new RDOSession();
                session.Logon("", "", false, false, false, false);
                RDOFolder folder = session.GetDefaultFolder(rdoDefaultFolders.olFolderContacts);
                RDOItems items = folder.Items.Restrict(strSQL);
                RDOContactItem cont;
                string currentGroup ="";
                int groupCounter = 1;
                for (int i = 1; i <= items.Count; i++)
                {
                    cont = (RDOContactItem)items.Item(i);
                    if (i == 1 && cont.get_Fields(GroupBy) != null && cont.get_Fields(GroupBy).ToString() != "")
                        currentGroup = cont.get_Fields(GroupBy).ToString();
                    if (cont.get_Fields(GroupBy) == null || currentGroup == cont.get_Fields(GroupBy).ToString())
                    {
                        groupCounter++;
                    }
                    else
                    {
                        Group gui = new Group();
                        gui.Count = groupCounter.ToString();
                        if (currentGroup == "")
                        {
                         gui.Name = mceTapiRexv2.Application.Current.getResString("1504", "", "");
                        }
                        else 
                        {
                            gui.Name = currentGroup;
                        }
                        if (currentGroup != "" || sFilter=="")
                            lstGroup.Add(gui);
                        if (cont.get_Fields(GroupBy) != null)
                            currentGroup = cont.get_Fields(GroupBy).ToString();
                        else
                            currentGroup = "";

                        groupCounter = 1;
                    }
                }
                //add last group
                Group lgui = new Group();
                lgui.Count = groupCounter.ToString();
                if (currentGroup == "")
                {
                    lgui.Name = mceTapiRexv2.Application.Current.getResString("1504", "", "");
                }
                else
                {
                    lgui.Name = currentGroup;
                }
                if (currentGroup != "" || sFilter == "")
                    lstGroup.Add(lgui);

               
            }
            FirePropertyChanged("GroupList");
        }

        private String buildCondition(int offset)
        {
            List<String> cond = new List<string>();
            string condition = "";
            if (this.sFilter != null && this.sFilter != "")
            {
                List<string> criterias = getProperties();
                 string keywordCond = "";
                string neg = "";
                string[] words = this.sFilter.Split(' ');
                int i = 0;
                foreach (string word in words)
                {
                    string searchExpression = word.Trim();
                    if (searchExpression == "" || searchExpression == " " || searchExpression == "-") break;
                    string condOp;
                    if (searchExpression.Substring(0, 1) == "-")
                    {
                        neg = "NOT";
                        condOp = " AND ";
                        searchExpression = searchExpression.Substring(1);
                    }
                    else condOp = " OR ";
                    if (i++ > 0) keywordCond += " AND ";
                    int j = 0;
                    foreach (string crit in criterias)
                    {
                        if (j++ == 0) keywordCond += "(";
                        else keywordCond += condOp;
                        keywordCond += "((" + crit + ") " + neg + " LIKE '%" + searchExpression + "%') ";
                    }
                    keywordCond += ")";
                    cond.Add(keywordCond);
                }
            }
            if (GroupBy != null && GroupBy != "")
            {
                if (CurrentGroup == mceTapiRexv2.Application.Current.getResString("1504", "", ""))
                {
                    cond.Add("(" + GroupBy + "='' OR " + GroupBy + " IS NULL )");

                }
                else cond.Add(GroupBy + "='" + CurrentGroup + "'");
            }
            string tempCondition = "";
            if (cond.Count > 0)
            {
                int j = 0;

                foreach (String sCondition in cond)
                {
                    if (j++ > 0) tempCondition += " AND ";
                    tempCondition += sCondition;
                }
            } 
            if (offset > 0)
            {
                if (tempCondition == "")
                    condition = " (ContactGUID NOT IN (SELECT TOP " + offset.ToString() + " ContactGUID FROM Contacts ORDER BY LastName ASC)) ";
                else
                {
                    condition = " (ContactGUID NOT IN (SELECT TOP " + offset.ToString() + " ContactGUID FROM Contacts " +
                        "WHERE " + tempCondition + " ORDER BY LastName DESC)) AND " + tempCondition;
                }
            }
            else condition = tempCondition;
            if (condition != "")
                condition = "WHERE " + condition;
            return condition;
           
          
        }
        private void loadContacts()
        {
            if (mceTapiRexv2.Application.Current.isDatabasePrimarySource())
                loadContactsFromDatabase();
            else loadContactsFromOutlook();
        }
        private void loadContactsFromDatabase()
        {
            String strSQL;
            lstContacts = new List<Contact>();
            string top = (mceTapiRexv2.Application.Current.itemsPP != "all") ? " TOP " + mceTapiRexv2.Application.Current.itemsPP : "";
            //If "all" is selected, int.parse crashes. Added try/catch to check it.
            int itemsPPtemp, offset;
            try
            {
                itemsPPtemp = int.Parse(mceTapiRexv2.Application.Current.itemsPP);
                offset = itemsPPtemp * this.currPage;
            }

            catch
            {
                offset = 0;
                itemsPPtemp =5;
            }
            string cond = buildCondition(offset);
            if (GroupBy != null && GroupBy != "")
            {
                strSQL = "SELECT " + top + " * , (Contacts.Picture IS NOT NULL) AS hasPicture,"+
                    "(SELECT COUNT(*) FROM Contacts " + cond + ") AS intCounter FROM  Contacts " +
                    buildCondition(offset) + " ORDER BY " + GroupBy + " DESC";
            }
            else strSQL = "SELECT " + top + " * , (Contacts.Picture IS NOT NULL) AS hasPicture ," +
                "(SELECT COUNT(*) FROM Contacts " + cond + ") AS intCounter FROM  Contacts " + 
                buildCondition(offset) + " ORDER BY LastName ASC";
            DataSet dr = db.SelectQuery(strSQL);
            DataTable dt = dr.Tables[0];
            lstContacts = new List<Contact>();
            bool maxPageUpdate = false;
            foreach (DataRow row in dt.Rows)
            {
                Contact c = new Contact(row);
                lstContacts.Add(c);
                if (!maxPageUpdate)
                {
                    int nCalls = Int32.Parse(row["intCounter"].ToString())+itemsPPtemp;
                    double temp = (double)nCalls / itemsPPtemp;
                    this.maxPage = (int)Math.Ceiling(temp) - 1;
                    FirePropertyChanged("hasNextPage");
                    FirePropertyChanged("hasPrevPage");
                    maxPageUpdate = true;
                }
            }
            FirePropertyChanged("ContactList");
        }
        public void loadContactsFromOutlook()
        {
            RDOSession session = new RDOSession();
            session.Logon("", "", false, false, false, false);
            RDOFolder folder = session.GetDefaultFolder(rdoDefaultFolders.olFolderContacts);
            String strSQL;
            lstContacts = new List<Contact>();
            string top = (mceTapiRexv2.Application.Current.itemsPP != "all") ? " TOP " + mceTapiRexv2.Application.Current.itemsPP : "";
            //If "all" is selected, int.parse crashes. Added try/catch to check it.
            int itemsPPtemp, offset;
            try
            {
                itemsPPtemp = int.Parse(mceTapiRexv2.Application.Current.itemsPP);
                offset = itemsPPtemp * this.currPage;
            }

            catch
            {
                offset = 0;
                itemsPPtemp = 5;
            }
            string cond = buildCondition(0);
            if (GroupBy != null && GroupBy != "")
            {
                strSQL = "SELECT  * " +
                    " FROM  Folder " +
                    buildCondition(0) + " ORDER BY " + GroupBy + " DESC";
            }
            else strSQL = "SELECT " + top + " * " +
                " FROM  Folder " +  buildCondition(0) + " ORDER BY LastName ASC";
            RDOItems items = folder.Items.Restrict("SELECT * FROM Folder WHERE MessageClass='IPM.Contact'");

            items = items.Restrict(strSQL.Replace("WHERE", "WHERE MessageClass='IPM.Contact' AND "));
           RDOContactItem contact;
            for (int i = 1; i <= Math.Min(itemsPPtemp,items.Count); i++)
            {
                contact = (RDOContactItem)items.Item(i+offset);
                if (contact != null)
                    lstContacts.Add(new Contact(contact,null));
                else break;
            }
            double temp = (double)items.Count / itemsPPtemp;
            this.maxPage = (int)Math.Ceiling(temp) - 1;
            FirePropertyChanged("hasNextPage");
            FirePropertyChanged("hasPrevPage");
            FirePropertyChanged("ContactList");
        }
        public bool GroupView
        {
            set { bGroupView = value; }
            get { return bGroupView; }
        }
        public String Keyword
        {
            set
            {
                if (this.sFilter != value)
                {
                    this.sFilter = value;
                    if (bGroupView)
                        loadGroups();
                    else loadContacts();
                    FirePropertyChanged("Keyword");
                }
            }
            get
            {
                return this.sFilter;
            }
        }
        public void RefreshList()
        {
            if (bGroupView)
                loadGroups();
            else loadContacts();
        }
        public bool hasPrevPage()
        {
            return (this.currPage > 0);
        }
        public bool hasNextPage()
        {
            return (this.currPage < this.maxPage - 1);
        }
        public void nextPage()
        {
            if (this.currPage < this.maxPage)
            {
                this.currPage++;
                FirePropertyChanged("hasNextPage");
                FirePropertyChanged("hasPrevPage");
                loadContacts();
            }
        }
        public void prevPage()
        {
            if (this.currPage > 0)
            {
                this.currPage--;
                FirePropertyChanged("hasNextPage");
                FirePropertyChanged("hasPrevPage");
                loadContacts();
            }
        }
     
    }
}
